#include "dask.h" 
#include <climits>
using namespace std;
DiskArm::DiskArm(){ 
 std::cout << "Please input current Cylinder:"; 
 std::cin >> CurrentCylinder; 
 
 //磁头⽅向 
 // 0 ：向⼩磁道号⽅向移动 
 // 1 ：向⼤磁道号⽅向移动 
 std::cout << "Please input current direction (0/1):"; 
 std::cin >> SeekDirection; 
 
 //输入磁盘请求数，请求道号 
 std::cout << "Please input request numbers:"; 
 std::cin >> RequestNumber; 
 
 std::cout << "Please input request cylinder string:"; 
 Request = new int[sizeof(int) * RequestNumber]; 
 Cylinder = new int[sizeof(int) * RequestNumber]; 
 for (int i = 0; i < RequestNumber; i++) 
 std::cin >> Request[i]; 
} 
 
DiskArm::~DiskArm(){ 
    delete[] Request;
    delete[] Cylinder;
} 
 
//初始化道号，寻道记录
void DiskArm::InitSpace(char *MethodName) { 
 std::cout << std::endl << MethodName << std::endl; 
 SeekNumber = 0; 
 SeekChang = 0; 
 for (int i = 0; i < RequestNumber; i++) 
 Cylinder[i] = Request[i]; 
} 
 
//统计报告算法执⾏情况
void DiskArm::Report() { 
 std::cout << std::endl; 
 std::cout << "Seek Number:" << SeekNumber << std::endl; 
 std::cout << "Change Direction:" << SeekChang << std::endl << std::endl; 
} 
 
void DiskArm::FCFS() { 
//先来先服务
/*按请求顺序处理*/
 int Current = CurrentCylinder; // 获取磁盘臂当前所在的柱面号
 int Direction = SeekDirection;  // 获取当前移动方向
 InitSpace("FCFS"); 
 
 std::cout << Current; 
 for (int i = 0; i < RequestNumber; i++) { 
    bool needChangeDirection = ((Cylinder[i] >= Current)&&!Direction) || ((Cylinder[i] < Current) && Direction); 
    if (needChangeDirection) { 
        Direction = !Direction; 
        SeekChang ++; //调头数加1 
        
        //报告当前响应的道号 
        std::cout << std::endl << Current << "->" << Cylinder[i]; 
    } else { 
    //不需要调头，报告当前响应的道号 
        std::cout << "->" << Cylinder[i]; 
    } 
    //累计寻道数，响应过的道号变为当前道号 
    SeekNumber += abs(Current - Cylinder[i]); 
    Current = Cylinder[i]; 
 } 
 
 //报告磁盘调度情况 
 Report(); 
} 
 
void DiskArm::SSTF(){ 
 //最短寻道时间优先算法
 /*每次选择离当前磁头位置最近的请求*/
 int Shortest;
    int Distance = 999999;
    int Direction = SeekDirection;
    int Current = CurrentCylinder;
    InitSpace("SSTF");
    std::cout << Current;
    for (int i = 0; i < RequestNumber; i++) {
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == -1) continue;
            if (Distance > abs(Current - Cylinder[j])) {
                Distance = abs(Current - Cylinder[j]);
                Shortest = j;
            }
        }
        if (((Cylinder[Shortest] >= Current) && !Direction) || ((Cylinder[Shortest] < Current) && Direction)) {
            SeekChang++;
            Direction = !Direction;
            std::cout << std::endl << Current << " -> " << Cylinder[Shortest];
        } else {
            std::cout << " -> " << Cylinder[Shortest];
        }
        SeekNumber += abs(Current - Cylinder[Shortest]);
        Current = Cylinder[Shortest];
        Distance = 999999;
        Cylinder[Shortest] = -1;
    }
    Report();

} 
 

 void DiskArm::SCAN(void) {
    //电梯算法
    /*磁头按固定方向移动直到没有请求，然后调头*/
    int NextCylinder;
    int Direction = SeekDirection; // 当前移动方向
    int Current = CurrentCylinder; // 磁盘臂当前位置
    int RequestCount = RequestNumber; // 待处理请求数
    InitSpace("SCAN"); // 初始化用于报告的空间
    cout << Current; // 报告当前位置
    while (RequestCount > 0) { // 继续直到所有请求都被服务完
        if (Direction) { // 向较高柱面号移动
            NextCylinder = 199;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] >= Current && Cylinder[j] < NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        } else { // 向较低柱面号移动
            NextCylinder = 0;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] <= Current && Cylinder[j] > NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        }
        // 报告下一个待服务的柱面号
        if (NextCylinder != Current) {
            cout << " -> " << NextCylinder;
        }
        // 更新总寻道距离
        SeekNumber += abs(Current - NextCylinder);
        // 将磁盘臂移动到下一个柱面
        Current = NextCylinder;

        if (NextCylinder == 199 || NextCylinder == 0) { // 当前方向没有请求
            Direction = !Direction; // 反转方向
            SeekChang++;
            cout<<endl;
            continue;
        }
        // 标记已服务的请求
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == NextCylinder) {
                Cylinder[j] = -1;
                RequestCount--; // 减少待处理请求计数
                break;
            }
        }
    }

    Report(); // 报告磁盘臂调度的摘要信息
}

void DiskArm::CSCAN(void) {
    //循环扫描算法
    /*磁头单向移动，到达边界后直接跳到另一端*/
    int NextCylinder;
    int Direction = SeekDirection; // 当前移动方向
    int Current = CurrentCylinder; // 磁盘臂当前位置
    int RequestCount = RequestNumber; // 待处理请求数
    InitSpace("CSCAN"); // 初始化用于报告的空间
    cout << Current; // 报告当前位置
    while (RequestCount > 0) { // 继续直到所有请求都被服务完
        if (Direction) { // 向较高柱面号移动
            NextCylinder = 199;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] >= Current && Cylinder[j] < NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        } else { // 向较低柱面号移动
            NextCylinder = 0;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] <= Current && Cylinder[j] > NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        }
        // 报告下一个待服务的柱面号
        if (NextCylinder != Current) {
            cout << " -> " << NextCylinder;
        }
        // 更新总寻道距离
        SeekNumber += abs(Current - NextCylinder);
        // 将磁盘臂移动到下一个柱面
        Current = NextCylinder;

        if (NextCylinder == 199 || NextCylinder == 0) { // 当前方向没有请求
            Direction = !Direction; // 反转方向
            SeekChang++;
            cout<<endl;
            if(NextCylinder==199){
                Current=0;
                SeekNumber+=(199-0);
                Direction = !Direction; // 反转方向
                SeekChang++;
                cout<<199<<" -> "<<0<<endl;
            }
            if(NextCylinder==0){
                Current=199;
                SeekNumber+=(199-0);
                Direction = !Direction; // 反转方向
                SeekChang++;
                cout<<0<<" -> "<<199<<endl;
            }
            continue;
        }
        // 标记已服务的请求
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == NextCylinder) {
                Cylinder[j] = -1;
                RequestCount--; // 减少待处理请求计数
                break;
            }
        }
    }

    Report(); // 报告磁盘臂调度的摘要信息
}

void DiskArm::LOOK(void) {
    /*不移动到磁盘边界*/
    int NextCylinder;
    int Direction = SeekDirection; // 当前移动方向
    int Current = CurrentCylinder; // 磁盘臂当前位置
    int RequestCount = RequestNumber; // 待处理请求数
    InitSpace("LOOK"); // 初始化用于报告的空间
    cout << Current; // 报告当前位置
    while (RequestCount > 0) { // 继续直到所有请求都被服务完
        if (Direction) { // 向较高柱面号移动
            NextCylinder = 199;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] >= Current && Cylinder[j] < NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        } else { // 向较低柱面号移动
            NextCylinder = 0;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] <= Current && Cylinder[j] > NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        }

        if (NextCylinder == 199 || NextCylinder == 0) { // 当前方向没有请求
            Direction = !Direction; // 反转方向
            SeekChang++;
            cout<<endl;
            continue;
        }

        // 报告下一个待服务的柱面号
        if (NextCylinder != Current) {
            cout << " -> " << NextCylinder;
        }
        // 更新总寻道距离
        SeekNumber += abs(Current - NextCylinder);
        // 将磁盘臂移动到下一个柱面
        Current = NextCylinder;

        // 标记已服务的请求
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == NextCylinder) {
                Cylinder[j] = -1;
                RequestCount--; // 减少待处理请求计数
                break;
            }
        }
    }

    Report(); // 报告磁盘臂调度的摘要信息
}

int main(int argc, char *argv[]) {
    DiskArm *dask = new DiskArm();
    dask->FCFS();
    dask->SSTF();
    dask->SCAN();
    dask->CSCAN();
    dask->LOOK();
}
